package org.hw.reference;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

public class Reference {
    static class TestObject {
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("TestObject finalize() called");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 创建一个引用队列
        ReferenceQueue<TestObject> queue = new ReferenceQueue<>();

        // 创建一个TestObject对象
        TestObject obj = new TestObject();

        // 创建一个虚引用，并将其与引用队列关联
        PhantomReference<TestObject> ref = new PhantomReference<>(obj, queue);
//        WeakReference<TestObject> ref = new WeakReference<>(obj, queue);
        // 只有虚引用无法获取原始值
        System.out.println(ref.get());
        // 移除对obj的强引用，以便垃圾回收器可以回收它
        obj = null;

        // 调用System.gc()建议JVM执行垃圾回收，但请注意这只是一个建议
        System.gc();

        // 等待一段时间，以便垃圾回收器有机会执行回收（这仍然是不确定的）
        Thread.sleep(1000);

        // 检查引用队列中是否有虚引用被加入
        // 这通常会在另一个线程中完成，但为了简化示例，我们在这里轮询
        while (true) {
            PhantomReference<TestObject> enqueuedRef = (PhantomReference<TestObject>) queue.poll();
//            WeakReference<TestObject> enqueuedRef = (WeakReference<TestObject>) queue.poll();
            if (enqueuedRef != null) {
                // 如果队列中有引用被加入，说明对应的对象可能已经被回收
                System.out.println("reference enqueued, indicating object may be reclaimed.");
                break;
            }
            // 为了避免无限循环，可以设置一个超时或条件来退出循环
            // 这里我们简单地再次等待一小段时间
            Thread.sleep(1000);
            System.gc();
        }

        // 注意：由于虚引用无法访问对象，因此你不能在这里访问obj的任何属性或方法
        // 虚引用的主要目的是跟踪对象被回收的时机
    }
}
